home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / TCP_IP / TNOS230S / GORMCB.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-06-28  |  7.5 KB  |  208 lines

  1. /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  2. #ifdef MSDOS
  3. #include <dpmi.h>
  4. #include <go32.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <sys/exceptn.h>
  8.  
  9. /*lint -save -e717 */
  10.  
  11. #if !defined(_lint)
  12. static char rcsid[] OPTIONAL = "$Id: gormcb.c,v 1.5 1997/06/28 16:46:13 root Exp root $";
  13. #endif
  14.  
  15. /* This code really can't be nested since the RMCB structure isn't copied,
  16.    so the stack check isn't really useful.  But someone may fix it someday.
  17.    On entry CS is known to be ours, ES is probably ours (since we passed it),
  18.    SS:ESP is locked 4K stack.  ES:EDI is regs structure, DS:ESI is RM SS:SP.
  19.    Do NOT enable interrupts in the user routine.  Thanks to ctm@ardi.com for
  20.    the improvements.  C. Sandmann 3/95 */
  21.  
  22. #define    STACK_WAS_MALLOCED    (1 << 0)
  23.  
  24. #define    FILL    0x00
  25.  
  26. static unsigned char wrapper_common[] = {
  27. /* 00 */ 0x06,                /*     push    es               */
  28. /* 01 */ 0x1e,                /*     push    ds               */
  29. /* 02 */ 0x06,                /*     push    es               */
  30. /* 03 */ 0x1f,                /*     pop     ds               */
  31. /* 04 */ 0x66, 0xb8,            /*     mov ax,            */
  32. /* 06 */ FILL, FILL,            /*         _our_selector    */
  33. /* 08 */ 0x8e, 0xd8,            /*     mov ds, ax               */
  34. /* 0a */ 0xff, 0x05,             /*     incl            */
  35. /* 0c */ FILL, FILL, FILL, FILL,    /*        _call_count        */
  36. /* 10 */ 0x83, 0x3d,            /*     cmpl            */
  37. /* 12 */ FILL, FILL, FILL, FILL,    /*         _in_this_handler    */
  38. /* 16 */ 0x00,                /*         $0            */
  39. /* 17 */ 0x75,                /*     jne            */
  40. /* 18 */ 0x33,                /*         bypass        */
  41. /* 19 */ 0xc6, 0x05,            /*     movb            */
  42. /* 1b */ FILL, FILL, FILL, FILL,    /*         _in_this_handler     */
  43. /* 1f */ 0x01,                /*         $1            */
  44. /* 20 */ 0x8e, 0xc0,            /*     mov es, ax               */
  45. /* 22 */ 0x8e, 0xe0,            /*     mov fs, ax               */
  46. /* 24 */ 0x8e, 0xe8,            /*     mov gs, ax               */
  47. /* 26 */ 0xbb,                /*     mov ebx,            */
  48. /* 27 */ FILL, FILL, FILL, FILL,    /*         _local_stack        */
  49. /* 2b */ 0xfc,                /*     cld                      */
  50. /* 2c */ 0x89, 0xe1,            /*     mov ecx, esp             */
  51. /* 2e */ 0x8c, 0xd2,            /*     mov dx, ss               */
  52. /* 30 */ 0x8e, 0xd0,            /*     mov ss, ax               */
  53. /* 32 */ 0x89, 0xdc,            /*     mov esp, ebx             */
  54. /* 34 */ 0x52,                /*     push edx                 */
  55. /* 35 */ 0x51,                /*     push ecx                 */
  56. /* 36 */ 0x56,                /*     push esi                 */
  57. /* 37 */ 0x57,                /*     push edi                 */
  58. /* 38 */ 0xe8,                /*     call                */
  59. /* 39 */ FILL, FILL, FILL, FILL,    /*         _rmcb                */
  60. /* 3d */ 0x5f,                /*     pop edi                  */
  61. /* 3e */ 0x5e,                /*     pop esi                  */
  62. /* 3f */ 0x58,                /*     pop eax                     */
  63. /* 40 */ 0x5b,                /*     pop ebx                     */
  64. /* 41 */ 0x8e, 0xd3,            /*     mov ss, bx               */
  65. /* 43 */ 0x89, 0xc4,            /*     mov esp, eax             */
  66. /* 45 */ 0xc6, 0x05,            /*     movb            */
  67. /* 47 */ FILL, FILL, FILL, FILL,    /*         _in_this_handler    */
  68. /* 4b */ 0x00,                /*         $0            */
  69. /* 4c */ 0x1f,                    /* bypass:  pop ds              */
  70. /* 4d */ 0x07,                /*     pop es                   */
  71.  
  72. /* 4e */ 0x8b, 0x06,            /*     mov eax,[esi]            */
  73. /* 50 */ 0x26, 0x89, 0x47, 0x2a,    /*     mov es:[edi+42],eax      */
  74. };
  75.  
  76. static unsigned char wrapper_retf[] = {
  77.          0x66, 0x26, 0x83, 0x47, 0x2e, 0x04,    /* add     es:[edi+46],0x4 */
  78.          0xcf                        /* iret                    */
  79. };
  80.  
  81. static unsigned char wrapper_iret[] = {
  82.          0x66, 0x8b, 0x46, 0x04,        /* mov     ax,[esi+4]      */
  83.          0x66, 0x26, 0x89, 0x47, 0x20,        /* mov     es:[edi+32],ax  */
  84.          0x66, 0x26, 0x83, 0x47, 0x2e, 0x06,    /* add     es:[edi+46],0x6 */
  85.          0xcf                    /* iret                    */
  86. };
  87.  
  88. unsigned long _go32_rmcb_stack_size = 32256;
  89.  
  90. static int setup_rmcb(unsigned char *wrapper, _go32_dpmi_seginfo *info,
  91.   __dpmi_regs *regs, unsigned char *stack, unsigned long stack_length)
  92. {
  93. #define    MALLOC_STACK()                    \
  94.   do {                            \
  95.       if (!stack_length) {                \
  96.       stack_length = _go32_rmcb_stack_size;        \
  97.       stack = (unsigned char *)malloc(stack_length);\
  98.       if (stack == 0) {                \
  99.         free(wrapper);                \
  100.         return 0x8015;                \
  101.       }                        \
  102.           if( _go32_dpmi_lock_data( stack,              \
  103.             stack_length) ) return 0x8015;              \
  104.       ((long *)stack)[0] = STACK_WAS_MALLOCED;    \
  105.       } else                        \
  106.       ((long *)stack)[0] = 0;            \
  107.       ((long *)stack)[1] = 0;                \
  108.       ((long *)stack)[2] = 0;                \
  109.   } while (0)
  110.  
  111.   MALLOC_STACK();
  112.   if( _go32_dpmi_lock_data(regs, sizeof(__dpmi_regs)))
  113.     return 0x8015;
  114.  
  115.   *(unsigned short *)(wrapper+0x06) = __djgpp_ds_alias;
  116.   *(long  *)(wrapper+0x0c) = (long) stack + 8;
  117.   *(long  *)(wrapper+0x12) = (long) stack + 4;
  118.   *(long  *)(wrapper+0x1b) = (long) stack + 4;
  119.   *(long  *)(wrapper+0x27) = (long) stack + (long) stack_length;
  120.   *(long  *)(wrapper+0x39) = (long) info->pm_offset - ((long)wrapper + 0x3d);
  121.   *(long  *)(wrapper+0x47) = (long) stack + 4;
  122.  
  123.   info->size = (unsigned long) wrapper;
  124.  
  125.   return __dpmi_allocate_real_mode_callback((void *)wrapper, regs,
  126.                                             (__dpmi_raddr *)&info->rm_offset);
  127. }
  128.  
  129.  
  130. static int _go32_dpmi_allocate_real_mode_callback_retf_with_stack(
  131.     _go32_dpmi_seginfo *info, __dpmi_regs *regs, unsigned char *stack,
  132.                             unsigned long stack_length)
  133. {
  134.   unsigned char *wrapper;
  135.  
  136. #define    CHECK_STACK()                            \
  137.   if ((stack_length && stack_length < 512) ||                \
  138.         (!stack_length && _go32_rmcb_stack_size < 512))    \
  139.     return 0x8015
  140.  
  141.   CHECK_STACK();
  142.  
  143.   wrapper = (unsigned char *)malloc(sizeof(wrapper_common) +
  144.                                  sizeof(wrapper_retf));
  145.   if (wrapper == 0)
  146.     return 0x8015;
  147.  
  148.   if( _go32_dpmi_lock_data( wrapper,
  149.     sizeof(wrapper_common) + sizeof(wrapper_retf)) ) return 0x8015;
  150.  
  151.   memcpy(wrapper, wrapper_common, sizeof(wrapper_common));
  152.   memcpy(wrapper+sizeof(wrapper_common), wrapper_retf, sizeof(wrapper_retf));
  153.  
  154.   return setup_rmcb(wrapper, info, regs, stack, stack_length);
  155. }
  156.  
  157. int _go32_dpmi_allocate_real_mode_callback_retf(_go32_dpmi_seginfo *info,
  158.                         __dpmi_regs *regs)
  159. {
  160.     return _go32_dpmi_allocate_real_mode_callback_retf_with_stack
  161.       (info, regs, (unsigned char *) 0, 0);
  162. }
  163.  
  164. static int _go32_dpmi_allocate_real_mode_callback_iret_with_stack(
  165.                               _go32_dpmi_seginfo *info, __dpmi_regs *regs,
  166.                               unsigned char *stack, unsigned long stack_length)
  167. {
  168.   unsigned char *wrapper;
  169.  
  170.   CHECK_STACK();
  171.  
  172.   wrapper = (unsigned char *)malloc(sizeof(wrapper_common) +
  173.                                  sizeof(wrapper_iret));
  174.   if (wrapper == 0)
  175.     return 0x8015;
  176.  
  177.   if( _go32_dpmi_lock_data( wrapper,
  178.     sizeof(wrapper_common) + sizeof(wrapper_iret)) ) return 0x8015;
  179.  
  180.   memcpy(wrapper, wrapper_common, sizeof(wrapper_common));
  181.   memcpy(wrapper+sizeof(wrapper_common), wrapper_iret, sizeof(wrapper_iret));
  182.  
  183.   return setup_rmcb(wrapper, info, regs, stack, stack_length);
  184. }
  185.  
  186. int _go32_dpmi_allocate_real_mode_callback_iret(_go32_dpmi_seginfo *info,
  187.                             __dpmi_regs *regs)
  188. {
  189.     return _go32_dpmi_allocate_real_mode_callback_iret_with_stack(info, regs,
  190.                                (unsigned char *) 0, 0);
  191. }
  192.  
  193. int _go32_dpmi_free_real_mode_callback(_go32_dpmi_seginfo *info)
  194. {
  195.   unsigned char *stack;
  196.  
  197.   stack = (unsigned char *)(*(long *)((long) info->size+0x12) - 4); /* fix prk */
  198.   if (*(long *) stack & STACK_WAS_MALLOCED)
  199.       free(stack);
  200.  
  201.   free((char *)info->size);
  202.   return __dpmi_free_real_mode_callback((__dpmi_raddr *)&info->rm_offset);
  203. }
  204.  
  205.  
  206. /*lint -restore */
  207. #endif
  208.